HEEx (HTML + EEx) is Phoenix LiveView’s template language that combines HTML with embedded Elixir. It provides HTML-aware interpolation, component support, compile-time validation, and smart change tracking.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/phoenixframework/phoenix_live_view/llms.txt
Use this file to discover all available pages before exploring further.
The ~H Sigil
HEEx templates are created using the~H sigil:
The
~H sigil requires an assigns variable to be in scope. This variable must be a map containing all the data your template needs.External Template Files
For larger templates, use.html.heex files instead of inline templates:
render/1, LiveView automatically looks for a .html.heex file with the same name.
Interpolation
Basic Interpolation
Use{...} for HTML-aware interpolation:
In Attributes
String Interpolation in Attributes
Special Attribute Values
- true
- false/nil
- Lists (class only)
Renders the attribute without a value:
class and style attributes render as empty strings instead of being omitted when false/nil, which has the same effect but enables rendering optimizations.Dynamic Attributes
Pass multiple attributes as a map or keyword list:Block Expressions
For multi-line Elixir code, use<%= ... %>:
Use
<%= %> when the block produces output, and <% %> for control flow keywords like end, else, etc.Special Attributes
:if - Conditional Rendering
Conditionally render elements::for - List Iteration
Iterate over collections:With Pattern Matching
:key for Change Tracking
By default, LiveView tracks items by index. Use:key for better change tracking:
Why use :key?
Why use :key?
Without
:key, inserting an item at the beginning causes all subsequent items to be re-rendered. With :key, only the new item is sent to the client.Combining :if and :for
HEEx’s
:for does not support multiple generators in one expression. For that, use EEx blocks::let - Slot Variables
Capture values passed from components::let.
Function Components
Invoke function components with HTML-like syntax:Local Components
Remote Components
With Attributes
Self-Closing vs Block Form
Comments
HEEx Comments
Comments that don’t appear in rendered HTML:HTML Comments
Regular HTML comments are preserved:Escaping Curly Braces
If you need literal{ or } in text:
Script and Style Tags
Curly brace interpolation is disabled inside<script> and <style> tags:
Disabling Interpolation
Usephx-no-curly-interpolation to disable {...} in any tag:
Code Formatting
HEEx templates support automatic formatting viamix format:
Preventing Formatting
Use thenoformat modifier:
Debug Annotations
Enable debug annotations to see where components are rendered:Debug Comments
Withdebug_heex_annotations: true:
Debug Attributes
Withdebug_attributes: true:
Template Best Practices
Avoid defining variables in templates
Avoid defining variables in templates
Don’t do this:Do this instead:Variables disable change tracking!
Keep logic out of templates
Keep logic out of templates
Don’t do this:Do this instead:
Never access the assigns variable directly
Never access the assigns variable directly
Don’t do this:Do this instead:Direct access to
assigns disables change tracking.Don't perform data loading in templates
Don't perform data loading in templates
Never do this:Always load in callbacks:
Common Patterns
Conditional Classes
Rendering Lists with Empty State
Tables
Forms
Loading States
Error Messages
Modal Dialogs
Compilation and Performance
HEEx templates are compiled to efficient Elixir code:- Static parts are computed once at compile time
- Dynamic parts are only re-computed when their assigns change
- Change tracking minimizes data sent over the wire
- Diffs are computed automatically and sent to the client
What Gets Tracked?
@user.name changes:
@user.idis not re-evaluated- Only the
@user.nametext is sent to the client - The
idattribute is not sent again
Summary
- Use
~Hsigil for inline templates or.html.heexfiles for external templates - Interpolate with
{@assign}for values and{expression}for computed values - Use
:if,:for, and:keyfor control flow - Invoke components with
<.component>syntax - Avoid variables and direct data access in templates
- Keep complex logic in functions, not templates
- Use
:keywith:forfor efficient list updates - Enable debug annotations during development